/*----------------------------------------------------------------------------
 *      U S B  -  K e r n e l
 *----------------------------------------------------------------------------
 * Name:    usbepfunc.c
 * Purpose: USB Custom User Module
 * Version: V1.00
 * Date:		2017/07
 *------------------------------------------------------------------------------*/
#include	<SN32F280.h>
#include	"..\Project\type.h"
#include	"..\Driver\Utility.h"

#include	"usbhw.h"
#include	"usbram.h"
#include	"usbdesc.h"
#include	"usbuser.h"
#include	"usbepfunc.h"

#include	"..\UsbHid\hid.h"
#include	"..\UsbHid\hiduser.h"


/*****************************************************************************
* Function		: USB_EPnINFunction
* Description	: SET EP1~EP6 IN token RAM
* Input				: 1. wEPNum: EP1~EP6
*								2. pData: transaction Data buffer
*								3. wBytecnt: Byte conuter Number of transaction
* Output			: None
* Return			: by EPn_RETURN_VALUE
* Note				: None
*****************************************************************************/
uint32_t	USB_EPnINFunction(uint32_t	wEPNum, uint8_t *pData, uint32_t	wBytecnt)
{
	volatile	uint32_t	*pUsbReg;
	uint32_t	wLoop, i,j;
	pUsbReg = (&SN_USB->EP0CTL) + wEPNum;
	
	if (!((*pUsbReg) & mskEPn_ENDP_EN))
			return	EPn_RETURN_DISABLE;
	
	// Only support EP1~EP4 and Byte counter < 64
	if ((wEPNum == USB_EP0) || (wEPNum > USB_EP6) || wBytecnt > 64)
		return EPn_RETURN_NOT_SUPPORT;			
	
	if ((*pUsbReg & (mskEPn_ENDP_EN|mskEPn_ENDP_STATE)) == (mskEPn_ENDP_EN|mskEPn_ENDP_STATE_NAK))
	{
		if (wUSB_EndpHalt[wEPNum] == USB_EPn_NON_HALT)
		{
			pUsbReg = &wUSB_EPnPacketsize[wEPNum];
			if (wBytecnt > *pUsbReg)
				return EPn_RETURN_OVER_MAX_SIZE;		//wBytecnt > EPn packet size

			//set EPn FIFO offset value to i
			j = wUSB_EPnOffset[wEPNum-1];
			for (wLoop=0; wLoop<wBytecnt;)	
			{
				i = wLoop>>2;
				i = *(pData+wLoop);
				wLoop++;
				i |= (*(pData+wLoop))<<8;
				wLoop++;
				i |= (*(pData+wLoop))<<16;
				wLoop++;
				i |= (*(pData+wLoop))<<24;
				wLoop++;
				fnUSBMAIN_WriteFIFO(j,i);
				j = j+4;
			}
			USB_EPnAck(wEPNum,wBytecnt);	// ACK hwByteCnt byte
			return EPn_RETURN_ACK_OK;
		}
		else//Halt = 1, return STALL
		{
			USB_EPnStall(wEPNum);					// EPn STALL
			return EPn_RETURN_STALL;
		}
	}
	else
	{
		return EPn_RETURN_ACK_BUSY;
	}
}
/*****************************************************************************
* Function		: EP3_Read_Function
* Description	: return mosue data
* Input				: None
* Output			: None
* Return			: None
* Note				: None
*****************************************************************************/
void EP3_Read_Function(void)
{
	volatile	uint32_t	*pUsbReg;
	uint32_t	wLoop, i;

	pUsbReg = (&SN_USB->EP0CTL) + USB_EP3;
	if ((*pUsbReg & (mskEPn_ENDP_EN|mskEPn_ENDP_STATE)) == (mskEPn_ENDP_EN|mskEPn_ENDP_STATE_NAK))
	{
		wLoop = ((*pUsbReg)&0x7F);
		wLoop >>=2;
		for(i=0; i<wLoop ;i++)
		{
			fnUSBINT_ReadFIFO((i<<2)+EP3_BUFFER_OFFSET_VALUE);
			rOutBuf[rEPOut_Frame_Index*64+i*4+0] = wUSBINT_ReadDataBuf&0xff;
			rOutBuf[rEPOut_Frame_Index*64+i*4+1] = (wUSBINT_ReadDataBuf>>8)&0xff;
			rOutBuf[rEPOut_Frame_Index*64+i*4+2] = (wUSBINT_ReadDataBuf>>16)&0xff;
			rOutBuf[rEPOut_Frame_Index*64+i*4+3] = (wUSBINT_ReadDataBuf>>24)&0xff;
		}
		SN_USB->INSTSC |= (1<<10);
		rEPOut_Frame_Index ++;
		if(rEPOut_Frame_Index>=64)
		{
			rEPOut_Frame_Index = 0;
			EP3_out_flag = 1;
		}
	}
	SN_USB->EP3CTL = 0xA0000000;
}

/*****************************************************************************
* Function		: USB_Test
* Description	: return mosue data
* Input				: None
* Output			: None
* Return			: None
* Note				: None
*****************************************************************************/
void	USB_Test()
{
	#define	circle 255
	
	switch (bUSB_MouseMode)
	{
		case	0:
		{
			if (bUSB_MouseCnt < circle)
			{
				wUSB_MouseData = 0x1<<8;
				bUSB_MouseCnt++;
			}
			else
			{
				bUSB_MouseCnt = 0;
				bUSB_MouseMode++;
			}
			break;
		}
		case	1:
		{
			if (bUSB_MouseCnt < circle)
			{
				wUSB_MouseData = 0xFF<<16;
				bUSB_MouseCnt++;
			}
			else
			{
				bUSB_MouseCnt = 0;
				bUSB_MouseMode++;
			}
			break;
		}
		case	2:
		{
			if (bUSB_MouseCnt < circle)
			{
				wUSB_MouseData = 0xFF<<8;
				bUSB_MouseCnt++;
			}
			else
			{
				bUSB_MouseCnt = 0;
				bUSB_MouseMode++;
			}
			break;			
		}
		case	3:
		{
			if (bUSB_MouseCnt < circle)
			{
				wUSB_MouseData = 0x1<<16;
				bUSB_MouseCnt++;
			}
			else
			{
				bUSB_MouseCnt = 0;
				bUSB_MouseMode = 0;
			}
			break;
		}
		default:
			break;
	}
}

